package com.base.common.viewmodel;

import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;

import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;

import com.base.common.app.BaseConstant;
import com.base.common.app.LoginUtils;
import com.base.common.model.http.err.ApiException;
import com.base.common.model.http.err.ERROR;
import com.base.common.netBeanPackage.LiveDataWrapper;
import com.base.common.utils.DialogUtils;
import com.base.common.utils.LogUtil;
import com.base.common.utils.UIUtils;
import com.base.common.view.widget.statelayout.StateLayout;
import com.jeremyliao.liveeventbus.LiveEventBus;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;

import java.lang.ref.WeakReference;

public abstract class BaseViewObserver<T> implements Observer<T> {

    protected WeakReference<StateLayout> mStateLayout;
    private WeakReference<Activity> context;

    private boolean isContainAPP_ERR = false;//该次的多个请求是否已出现了内部错误


    /**
     * 不对请求状态进行处理
     */
    public BaseViewObserver() {

    }


    /**
     * 只对请求成功和失败进行处理
     */
    public BaseViewObserver(Activity context) {
        this.context = new WeakReference<>(context);
    }

    /**
     * 传入状态布局 搭配response自动显示状态
     *
     * @param stateLayout
     */
    public BaseViewObserver(StateLayout stateLayout) {
        if (stateLayout != null) {
            this.mStateLayout = new WeakReference<>(stateLayout);
            mStateLayout.get().setRefreshLayout(isRefreshLayoutData());
        }
    }

    public BaseViewObserver(Object object) {

        if (object instanceof Activity) {
            this.context = new WeakReference<>((Activity) object);
        } else if (object instanceof Fragment) {
            this.context = new WeakReference<>(((Fragment) object).getActivity());
        } else if (object instanceof StateLayout) {
            this.mStateLayout = new WeakReference<>((StateLayout) object);
            mStateLayout.get().setRefreshLayout(isRefreshLayoutData());
        }


    }


    /**
     * 当出现外部错误时，只有发送一个ERROR  一会结速这一串请求，并不会发射onComplete
     * 当出现内部错误时，请求已返回对这次请求来说是成功的，有可能会发射 onComplete
     * <p>
     * 现对，发射状态调整，不管是内部还是外部错误时，都会发射onComplete,并且只会发射一次，
     */
    @Override
    public void onChanged(T t) {
        if (t instanceof LiveDataWrapper) {
            LiveDataWrapper liveDataWrapper = (LiveDataWrapper) t;
            switch (liveDataWrapper.status) {
                case LOADING:
                    LogUtil.d("BaseViewObserver", "加载中");
                    loadLayout();
                    onStart();
                    break;
                case ERROR:

                    if (liveDataWrapper.error != null) {
                        LogUtil.d("BaseViewObserver", liveDataWrapper.error.getCode() + "  " + liveDataWrapper.error.getMessage());
                        if (liveDataWrapper.error.getCode() >= ERROR.ERR400) {
                            notNetWorkLayout();
                        } else {
                            errorLayout();
                        }
                        //外部网络错误
                        onNetError(liveDataWrapper.error);
                    }
                    //外部错误，只要便会中断，只会发射一次
                    onComplete();
                    break;
                case APP_ERROR:
                    if (liveDataWrapper.error != null) {
                        LogUtil.d("BaseViewObserver", liveDataWrapper.error.getMessage());

                        onAppError(liveDataWrapper.error);
                        if (liveDataWrapper.error.getCode() == ERROR.LOGIN_OUT) {
                            loginLayout();
                        } else {
                            errorLayout();
                        }
                    }
                    //内部错误，不会中断，可能发射多次,故手动中断
                    if (!isContainAPP_ERR) {
                        onComplete();
                        isContainAPP_ERR = true;
                    }

                    break;
                case SUCCESS:

                    LogUtil.d("BaseViewObserver", "成功");
                    if (isEmptyData(t)) {
                        onEmptyLayout();
                        onSuccessResultNull();
                    } else {
                        contentLayout(t);
                        onSuccess(t);
                    }

                    break;
                case COMPLETE://所有请求都成功时回调,只会回调一次
                    LogUtil.d("BaseViewObserver", "请求完毕");
                    onComplete();
                    break;

            }
        }
    }


    protected void onEmptyLayout() {
        if (null != mStateLayout) {
            mStateLayout.get().showEmptyView();
        } else if (null != context) {
            DialogUtils.dismiss(context.get());
        }
    }

    private void contentLayout(T data) {
        if (null != mStateLayout) {
            if (isEmptyData(data)) {
                mStateLayout.get().showEmptyView();
            } else {
                mStateLayout.get().showContentView();
            }
        } else if (null != context) {
            DialogUtils.dismiss(context.get());
        }
    }

    private void loginLayout() {
        if (null != mStateLayout) {
            mStateLayout.get().showLoginView();
        } else if (null != context) {
            //发送需要弹出登录页面
            if (isSendNeedLogin()) {
                LoginUtils.loginIn();
                UIUtils.showToastSafes("未登录请登录");
            }
            DialogUtils.dismiss(context.get());
        }
    }

    private void notNetWorkLayout() {
        if (null != mStateLayout) {
            mStateLayout.get().showNoNetworkView();
        } else if (null != context) {
            DialogUtils.dismiss(context.get());
        }
    }

    private void errorLayout() {

        if (null != mStateLayout) {
            mStateLayout.get().showErrorView();
        } else if (null != context) {
            DialogUtils.dismiss(context.get());
        }
    }

    private void loadLayout() {
        if (null != mStateLayout) {
            mStateLayout.get().showLoadingView();
        } else if (null != context) {
            DialogUtils.waitingDialog(context.get());
        }
    }

    //是否发送需要登录事件
    public boolean isSendNeedLogin() {
        return true;
    }


    //判断结果是否为空
    public boolean isEmptyData(T data) {
        return false;
    }


    //是否是下拉刷新数据源
    public boolean isRefreshLayoutData() {
        return false;
    }

    // 开始时回调
    protected void onStart() {

    }

    //请求结束时回调
    protected void onComplete() {
        if (null != context) {
            DialogUtils.dismiss(context.get());
        }
    }

    private void findSmartRefreshLayout(ViewGroup viewGroup, SmartRefreshLayout[] smartRefreshLayouts) {
        if (viewGroup != null && smartRefreshLayouts != null) {
            int count = viewGroup.getChildCount();
            for (int i = 0; i < count; i++) {
                //如果找到了就中断
                if (smartRefreshLayouts[0] != null) {
                    break;
                }
                View view = viewGroup.getChildAt(i);
                if (view instanceof SmartRefreshLayout) {
                    smartRefreshLayouts[0] = (SmartRefreshLayout) view;
                    break;
                } else if (view instanceof ViewGroup) {
                    findSmartRefreshLayout((ViewGroup) view, smartRefreshLayouts);
                }
            }
        }
    }


    //app内部错误时回调
    protected void onAppError(ApiException error) {
        if (error.getCode() != ERROR.LOGIN_OUT) {
            UIUtils.showToastSafesClose(error.getMessage());
        }
        LogUtil.e(error.getMessage());
        onError(error);
    }

    //服务器外部错误回调
    protected void onNetError(ApiException error) {
        LogUtil.e(error.getMessage() + error.getUrl() == null ? "" : "\nurl: " + error.getUrl());
        UIUtils.showToastSafesClose(error.getMessage());
        onError(error);
    }

    protected void onError(ApiException error) {

    }


    protected void onSuccessResultNull() {

    }

    protected abstract void onSuccess(T data);


}
